package com.mazaiting.minio.config;

import com.mazaiting.common.core.domain.result.ResultCode;
import com.mazaiting.minio.ex.MinioException;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * minio 自动配置
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
@ConditionalOnClass(MinioClient.class)
@EnableConfigurationProperties(MinioProperties.class)
public class MinioAutoConfiguration {

    private final MinioProperties minioProperties;

    /**
     * 配置 minio 客户端
     * @return minio 客户端
     */
    @Bean
    public MinioClient minioClient() throws MinioException {
        log.info("开始初始化MinioClient, url为{}, accessKey为:{}, secretKey为: {}", minioProperties.getUrl(), minioProperties.getAccessKey(), minioProperties.getSecretKey());
        // 配置客户端
        MinioClient minioClient = MinioClient
                .builder()
                .endpoint(minioProperties.getUrl())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
        // 设置超时时间
        minioClient.setTimeout(
                minioProperties.getConnectTimeout(),
                minioProperties.getWriteTimeout(),
                minioProperties.getReadTimeout()
        );
        // 启动保护, 是否开启校验桶
        if (minioProperties.isCheckBucket()) {
            log.info("checkBucket为{}, 开始检测桶是否存在", minioProperties.isCheckBucket());
            String bucketName = minioProperties.getBucketName();
            // 校验桶是否存在
            if (!checkBucket(bucketName, minioClient)) {
                log.info("文件桶[{}]不存在, 开始检查是否可以新建桶", bucketName);
                // 是否自动创建桶
                if (minioProperties.isCreateBucket()) {
                    log.info("createBucket为{},开始新建文件桶", minioProperties.isCreateBucket());
                    createBucket(bucketName, minioClient);
                }
            }
            log.info("文件桶[{}]已存在, minio客户端连接成功!", bucketName);
        }
        return minioClient;
    }

    /**
     * 校验桶是否存在
     * @param bucketName 桶名
     * @param minioClient minio 客户端
     * @return true: 存在; false: 不存在
     */
    private boolean checkBucket(String bucketName, MinioClient minioClient) throws MinioException {
        boolean isExists;
        try {
            isExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("校验桶是否存在异常: {}.", e.getMessage());
            throw new MinioException(ResultCode.MINIO_CHECK_BUCKET_ERROR);
        }
        return isExists;
    }

    /**
     * 创建桶
     * @param bucketName 桶名
     * @param minioClient minio 客户端
     */
    private void createBucket(String bucketName, MinioClient minioClient) throws MinioException {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            log.info("文件桶[{}]新建成功, minio客户端已连接", bucketName);
        } catch (Exception e) {
            log.error("创建默认桶异常: {}.", e.getMessage());
            throw new MinioException(ResultCode.MINIO_CREATE_BUCKET_FAILED);
        }
    }
}